package com.cdd.servicebankcard.service.impl;

import com.cdd.servicebankcard.dao.AccountInfoMapper;
import com.cdd.servicebankcard.model.AccountInfo;
import com.cdd.servicebankcard.service.AccountService;
import org.dromara.hmily.annotation.Hmily;
import org.dromara.hmily.core.concurrent.threadlocal.HmilyTransactionContextLocal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @Description TODO
 * @Author: cdd
 * @Date: 2020/7/9 15:31
 * @Version: 1.0
 */
@Service
public class AccountServiceImpl implements AccountService {

    private static final Logger log = LoggerFactory.getLogger(AccountServiceImpl.class);

    @Resource
    AccountInfoMapper accountInfoMapper;

    @Override
    public AccountInfo getById(Long id) {
        return accountInfoMapper.selectByPrimaryKey(id);
    }

    @Override
    @Transactional
    @Hmily(confirmMethod = "doConfirm", cancelMethod = "doCancel")
    public int updateAccountById(Integer amount) {
        // 获取全局事务id
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        System.out.println(transId + "：执行到service-bankcard#doTry方法");

        // 幂等判断
        if(accountInfoMapper.isExistTry(transId) > 0) return 1;
        // 悬挂处理
        if(accountInfoMapper.isExistConfirm(transId) > 0 || accountInfoMapper.isExistCancel(transId) > 0) return 1;

        // 给张三的银行卡账户加钱
        AccountInfo accountInfo = getById(1L);
        accountInfo.setBalance(accountInfo.getBalance() + amount);
        int flag = accountInfoMapper.updateByPrimaryKeySelective(accountInfo);
        if(flag != 1) throw new RuntimeException("张三的银行卡账户加钱失败");

        // 插入try执行记录
        accountInfoMapper.addTry(transId);

        return 1;
    }

    @Transactional
    public int doConfirm(Integer amount) {
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        System.out.println(transId + "：执行到service-bankcard#doConfirm方法");
        return 1;
    }

    @Transactional
    public int doCancel(Integer amount) {
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        System.out.println(transId + "：执行到service-bankcard#doCancel方法");

        // 处理空回滚情况
        if(accountInfoMapper.isExistTry(transId) == 0){
            System.out.println("service-bankcard#doTry部分执行失败，无需回滚");
            return 1;
        }

        // 幂等处理
        if(accountInfoMapper.isExistCancel(transId) > 0){
            System.out.println("service-bankcard#doCancel已经执行过，无需再次doCancel");
            return 1;
        }

        // 把doTry中增加的金额再扣减
        AccountInfo accountInfo = getById(1L);
        accountInfo.setBalance(accountInfo.getBalance() - amount);
        int flag = accountInfoMapper.updateByPrimaryKeySelective(accountInfo); // 支付宝出账
        if(flag != 1) throw new RuntimeException("张三的银行卡账户doCancel金额失败");

        // 添加doCancel日志
        accountInfoMapper.addCancel(transId);

        return 1;
    }
}
